const { ccclass, property } = cc._decorator;

enum holderState {
    down = 0,
    uping = 1,
    up = 2,
    downing = 3
}

@ccclass
export default class elevatorControl extends cc.Component {

    @property(cc.Node)
    base: cc.Node = null;

    @property(cc.Node)
    holder: cc.Node = null;

    @property(cc.Node)
    step: cc.Node = null;

    @property
    get riseHeight() {//台阶到地面高度
        return this._HolderHeight + this._stepHeight;
    }

    @property
    maxHeight: number = 500;

    @property(cc.SpriteFrame)
    holderSprite: cc.SpriteFrame = null;

    @property(cc.SpriteFrame)
    stepSprite: cc.SpriteFrame = null;

    @property
    speed: number = 100;

    @property
    offsetUp: number = 0;
    @property
    offsetDown: number = 0;
    index: number = 0;

    poolNodes: cc.NodePool = new cc.NodePool();
    _State: holderState = holderState.down;
    _HolderNode: cc.Node = null;//传送带节点
    _NodeHeight: number = 0;//每节高度
    _holderLength: number = 0;//当前传送带长度
    _HolderHeight: number = 0;//升高的高度
    _stepHeight = 0;//初始距离地面高度
    _stepY = 0;//底座高度
    _isStop: boolean = false;
    _Collider: cc.PhysicsBoxCollider = null;

    onLoad() {
        this.step.anchorY = 0;
        this.step.y = this.base.height;
        this._stepY = this.base.height;
        this.holder.anchorY = 1;
        this.holder.y = this.step.y;
        this._HolderNode = new cc.Node();
        this._HolderNode.anchorY = 1;
        let sprite = this._HolderNode.addComponent(cc.Sprite);
        sprite.spriteFrame = this.holderSprite;
        this._NodeHeight = this._HolderNode.height;
        this.holder.width = this._HolderNode.width;
        this.holder.height = this._stepY;
        this.holder.y = this._stepY;
        this._stepHeight = this.base.height + this.step.height - this.offsetUp;
        this._Collider = this.holder.getComponent(cc.PhysicsBoxCollider);

        this.node.on("HeroContact", this.setHeroContact, this);
        this.node.on("StopStep", this.setStopEvent, this);
        this.node.on("ImpedeInContact", this.setImpedeIn, this);
        this.node.on("ImpedeOutContact", this.setImpedeOut, this);
        this.step.getComponent(cc.Sprite).spriteFrame = this.stepSprite;
        let collider = this.step.getComponent(cc.PhysicsBoxCollider);
        collider.tag = TagStep;
        let nodeSize = this.step.getContentSize();
        collider.size = new cc.Size(nodeSize.width - 15, nodeSize.height - this.offsetUp - this.offsetDown);
        collider.offset.y = (this.offsetDown - this.offsetUp + this.step.height) / 2;

        let areadown = this.step.addComponent(cc.BoxCollider);
        areadown.tag = TagStep;
        areadown.size = new cc.Size(collider.size.width + 15, collider.size.height + 4);
        areadown.offset.y = collider.offset.y;

        let areaup = this.step.addComponent(cc.BoxCollider);
        areaup.tag = TagWayTrack;
        areaup.size = new cc.Size(nodeSize.width - 10, this.offsetUp);
        areaup.offset.y = this._stepHeight - this.offsetUp / 2;
    }
    goUp() {
        this._State = holderState.uping;
    }
    goDown() {
        this._State = holderState.downing;
    }
    stop() {
        this._isStop = true;
    }
    start() {
        this._isStop = false;
    }
    setStopEvent(event: cc.Event.EventCustom) {
        this._isStop = event.getUserData();
    }
    setHeroContact(event: cc.Event.EventCustom) {
        if (event.getUserData()) {
            this.goUp();
        }
        else {
            this.goDown();
        }
        event.stopPropagation();
    }
    setImpedeIn(event: cc.Event.EventCustom) {
        if (event.getUserData()) {
            if (this._State == holderState.uping) {
                this.stop();
            }
        }
        else {
            if (this._State == holderState.downing) {
                this.stop();
            }
        }
        event.stopPropagation();
    }
    setImpedeOut(event: cc.Event.EventCustom) {
        let ud: string = event.getUserData();
        if (ud.indexOf('u') >= 0) {
            if (this._State == holderState.uping) {
                event.stopPropagation();
                return;
            }
        }
        else if (ud.indexOf('d') >= 0) {
            if (this._State == holderState.downing) {
                event.stopPropagation();
                return;
            }
        }
        this.start();
        event.stopPropagation();
    }
    addHolder() {
        let newNode = this.poolNodes.get();
        if (!newNode) {
            newNode = cc.instantiate(this._HolderNode);
        }
        newNode.y = 0 - this._holderLength;
        this.holder.addChild(newNode);
        this._holderLength += this._NodeHeight;
        let _size = this.holder.getContentSize();
        _size.height = this._holderLength;
        this._Collider.size = _size;
        this._Collider.offset.y = (newNode.y - this._stepHeight) / 2;
        this._Collider.apply();

    }
    deleteHolder() {
        if (this.holder.children.length > 0) {
            this.poolNodes.put(this.holder.children[this.holder.children.length - 1]);
            this._holderLength -= this._NodeHeight;
        }
    }
    doHolder(move: number) {
        let height = this._HolderHeight + move;
        if (height >= this.maxHeight - this._stepHeight) {
            this._HolderHeight = this.maxHeight - this._stepHeight;
            this._State = holderState.up;
        }
        else if (height <= 0) {
            this._HolderHeight = 0;
            this._State = holderState.down;
        }
        else {
            this._HolderHeight = height;
        }
        if (this._State == holderState.uping) {
            if (this._holderLength <= this._HolderHeight)
                this.addHolder();
        }
        else if (this._State == holderState.downing) {
            if (this._holderLength - this._NodeHeight >= this._HolderHeight)
                this.deleteHolder();
        }
        let stepHeight = this._stepY + this._HolderHeight;
        this.holder.height = stepHeight;
        this.holder.y = stepHeight;
        this.step.y = stepHeight;
    }
    update(dt) {
        if (this._isStop)
            return;
        if (this._State == holderState.downing) {
            this.doHolder(0 - dt * this.speed);
        }
        else if (this._State == holderState.uping) {
            this.doHolder(dt * this.speed);
        }
    }
}
